home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / shadowlib.lha / shadow / Examples / Source / gui.c < prev    next >
C/C++ Source or Header  |  1992-11-13  |  59KB  |  1,866 lines

  1. /*
  2.  * First run attempt at a functional GUI library.
  3.  * I agree, it sucks, but it's good enough, as Americans USED to
  4.  *  say.
  5.  *
  6.  * COPYRIGHT: 1991, 1992 David C. Navas
  7.  *            License granted to SwRI to modify and use as per site
  8.  *             license.  Further distribution license rights granted
  9.  *             upon receipt of agreed upon compensation.
  10.  *            All Other Rights Reserved by Author
  11.  */
  12. #include "gui.h"
  13.  
  14. /*
  15.  * Of course!  max() is in string.h....
  16.  */
  17. #define USE_BUILTIN_MATH
  18. #include <string.h>
  19.  
  20. #include <libraries/diskfont.h>
  21. #include <libraries/asl.h>
  22. #include <clib/diskfont_protos.h>
  23. #include <clib/graphics_protos.h>
  24. #include <clib/asl_protos.h>
  25. #include <clib/utility_protos.h>
  26.  
  27. #include <pragmas/diskfont_pragmas.h>
  28. #include <pragmas/graphics_pragmas.h>
  29. #include <pragmas/asl_pragmas.h>
  30. #include <pragmas/utility_pragmas.h>
  31.  
  32. #include <shadow/coreRoot.h>
  33. #include <shadow/coreMeta.h>
  34. #include <shadow/misc.h>
  35. #include <shadow/process.h>
  36. #include <shadow/semaphore.h>
  37. #include <shadow/shadowBase.h>
  38. #include <shadow/shadow_proto.h>
  39. #include <shadow/shadow_pragmas.h>
  40.  
  41. #include <dos/dostags.h>
  42. #include <ipc.h>
  43. #include <ipc_proto.h>
  44.  
  45. extern struct Library * __far SysBase;
  46. extern struct Library * __far DOSBase;
  47. struct Library * __far GadToolsBase;
  48. struct Library * __far IntuitionBase;
  49. extern struct Library * __far DiskfontBase;
  50. extern struct Library * __far GfxBase;
  51. extern struct Library * __far ShadowBase;
  52. extern struct Library * __far UtilityBase;
  53. struct Library * __far AslBase;
  54.  
  55. /*
  56.  * external class definitions.
  57.  */
  58. extern char GuiProcClassName[],
  59.             AslProcClassName[],
  60.             GuiTaskName[],
  61.             GuiClassName[],
  62.             WindowClassName[],
  63.             GadgTClassName[],
  64.             AslClassName[];
  65.  
  66. void RemoveWinSafely(struct Window *win);
  67. void StripIntuiMessages(struct MsgPort *port, struct Window *win);
  68.  
  69. struct TextAttr __far ta = {"topaz.font", 11, FS_NORMAL,
  70.                             FPF_ROMFONT | FPF_DISKFONT};
  71. struct TextFont * __far tf;
  72.  
  73. OBJECT __GlobalFocus = NULL;  /* one valid focus only */
  74.  
  75.  
  76. /*
  77.  * ==========================================================================
  78.  * =                                                                        =
  79.  * =           Class definition for the GUI process.                        =
  80.  * =                                                                        =
  81.  * ==========================================================================
  82.  */
  83. ATTRIBUTE_TAG guiProcAttrs[] =
  84.                         {
  85.                            ATTR_GUIPROCESS, sizeof(struct GuiProcess), NULL,
  86.                            TAG_END
  87.                         };
  88.  
  89. ARGUMENT_TAG REF_AssociateGuiProcObject[] =
  90.                         {
  91.                            {
  92.                               'JSTR', 4, 0
  93.                            },
  94.                            {
  95.                               TAG_END, SHADOW_RETURN_OBJECT, 0
  96.                            }
  97.                         };
  98.  
  99. void __saveds *AssociateGuiProcObject(METHOD_ARGS, char *name);
  100. void __saveds HandleGuiProcObject(METHOD_ARGS);
  101. void __saveds DisGuiProcObject(METHOD_ARGS);
  102.  
  103. METHOD_TAG guiProcMethods[] =
  104.                         {
  105.                            {
  106.                               METH_PROC_ASSOCIATE,
  107.                               NULL, NULL,
  108.                               INVOKE_FORCE_SYNC,
  109.                               METH_FLAG_OBJECT_AS_DEST, 0,
  110.                               (METHODFUNCTYPE)AssociateGuiProcObject,
  111.                                  REF_AssociateGuiProcObject
  112.                            },
  113.                            {
  114.                               METH_PROC_HANDLER,
  115.                               NULL, NULL,
  116.                               INVOKE_FORCE_SYNC,
  117.                               METH_FLAG_OBJECT_AS_DEST, 0,
  118.                               (METHODFUNCTYPE)HandleGuiProcObject, NULL
  119.                            },
  120.                            {
  121.                               METH_PROC_DISASSOCIATE,
  122.                               NULL, NULL,
  123.                               INVOKE_FORCE_SYNC,
  124.                               METH_FLAG_OBJECT_AS_DEST, 0,
  125.                               (METHODFUNCTYPE)DisGuiProcObject, NULL
  126.                            },
  127.                            TAG_END
  128.                         };
  129.  
  130.  
  131. void __saveds *InitAslProcObject(METHOD_ARGS, char *name,
  132.                                  OBJECT junk,
  133.                                  struct SignalSemaphore *semJunk,
  134.                                  struct TagItem *tags);
  135. extern ARGUMENT_TAG REF_InitAslProcObject[];
  136.  
  137. METHOD_TAG aslProcMethods[] =
  138.                         {
  139.                            {
  140.                               METH_INIT,
  141.                               NULL, NULL,
  142.                               INVOKE_CALL,
  143.                               METH_FLAG_OBJECT, 0,
  144.                               (METHODFUNCTYPE)InitAslProcObject,
  145.                                  REF_InitAslProcObject
  146.                            },
  147.                            TAG_END
  148.                         };
  149.  
  150. /*
  151.  * ==========================================================================
  152.  * =                                                                        =
  153.  * =           Class definition for GUI type of objects.                    =
  154.  * =                                                                        =
  155.  * ==========================================================================
  156.  */
  157.  
  158. ATTRIBUTE_TAG guiAttrs[] =
  159.                         {
  160.                            ATTR_GUICHILDREN, FLAG_ATTR_WATCHED | SHADOW_TREE,
  161.                                              NULL,
  162.                            ATTR_GUISTRUCT, sizeof(struct GUIStruct), NULL,
  163.                            ATTR_GUIOUTPUT, sizeof(struct OutputStruct), NULL,
  164.                            TAG_END
  165.                         };
  166. METHOD_TAG guiMethods[] =
  167.                         {
  168.                            {
  169.                               METH_REMOVE,
  170.                               NULL, NULL,
  171.                               INVOKE_SYNC,
  172.                               METH_FLAG_OBJECT, 0,
  173.                               (METHODFUNCTYPE)GuiRemoveMethod, NULL
  174.                            },
  175.                            {
  176.                               METH_DESTROY,
  177.                               NULL, NULL,
  178.                               INVOKE_SYNC,
  179.                               METH_FLAG_OBJECT, 0,
  180.                               (METHODFUNCTYPE)GuiDestroyMethod, NULL
  181.                            },
  182.                            {
  183.                               METH_INIT,
  184.                               NULL, NULL,
  185.                               INVOKE_SYNC,
  186.                               METH_FLAG_OBJECT, 0,
  187.                               GuiInitMethod, REF_GuiInitMethod
  188.                            },
  189.                            {
  190.                               METH_GUI_STATE,
  191.                               NULL, NULL,
  192.                               INVOKE_SYNC,
  193.                               METH_FLAG_OBJECT, 0,
  194.                               (METHODFUNCTYPE)GuiStateNotify,
  195.                                  REF_GuiStateNotify
  196.                            },
  197.                            {
  198.                               METH_GUI_FOCUS,
  199.                               NULL, NULL,
  200.                               INVOKE_SYNC,
  201.                               METH_FLAG_OBJECT, 0,
  202.                               (METHODFUNCTYPE)GuiGrabFocus, REF_GuiGrabFocus
  203.                            },
  204.                            TAG_END
  205.                         };
  206.  
  207. /*
  208.  * ==========================================================================
  209.  * =                                                                        =
  210.  * =           Class definition for window objects.                         =
  211.  * =                                                                        =
  212.  * ==========================================================================
  213.  */
  214.  
  215. ATTRIBUTE_TAG winAttrs[] =
  216.                         {
  217.                            ATTR_WINDOW, sizeof(struct WindowObject), NULL,
  218.                            TAG_END
  219.                         };
  220.  
  221. ARGUMENT_TAG REF_MoveWin[],
  222.              REF_PreTitleWindow[];
  223.  
  224. void MoveWin(METHOD_ARGS, long *);
  225. void WinUpdateMethod(METHOD_ARGS);
  226. BOOL PreTitleWindow(METHOD_ARGS, char *string);
  227.  
  228. METHOD_TAG winMethods[] =
  229.                         {
  230.                            {
  231.                               METH_INIT,
  232.                               NULL, NULL,
  233.                               INVOKE_SYNC,
  234.                               METH_FLAG_OBJECT, 0,
  235.                               WinOpenMethod, REF_WinOpenMethod
  236.                            },
  237.                            {
  238.                               METH_DESTROY,
  239.                               NULL, NULL,
  240.                               INVOKE_SYNC,
  241.                               METH_FLAG_OBJECT, 0,
  242.                               (METHODFUNCTYPE)WinDestroyMethod, NULL
  243.                            },
  244.                            {
  245.                               METH_WINDOW_CLOSE,
  246.                               NULL, NULL,
  247.                               INVOKE_SYNC,
  248.                               METH_FLAG_OBJECT, 0,
  249.                               (METHODFUNCTYPE)WinCloseMethod, NULL
  250.                            },
  251.                            {
  252.                               METH_WINDOW_PRETITLE,
  253.                               NULL, NULL,
  254.                               INVOKE_ASYNC,
  255.                               METH_FLAG_OBJECT, 0,
  256.                               (METHODFUNCTYPE)PreTitleWindow,
  257.                                  REF_PreTitleWindow
  258.                            },
  259.                            {
  260.                               METH_WINDOW_UPDATE,
  261.                               NULL, NULL,
  262.                               INVOKE_SYNC,
  263.                               METH_FLAG_OBJECT, 0,
  264.                               (METHODFUNCTYPE)WinUpdateMethod, NULL
  265.                            },
  266.                            {
  267.                               METH_WINDOW_MOVE,
  268.                               NULL, NULL,
  269.                               INVOKE_CALL,
  270.                               METH_FLAG_OBJECT, 0,
  271.                               (METHODFUNCTYPE)MoveWin,
  272.                                  REF_MoveWin
  273.                            },
  274.                            TAG_END
  275.                         };
  276.  
  277. /*
  278.  * ==========================================================================
  279.  * =                                                                        =
  280.  * =           Class definition for gadget objects.                         =
  281.  * =                                                                        =
  282.  * ==========================================================================
  283.  */
  284.  
  285. ATTRIBUTE_TAG gadAttrs[] =
  286.                         {
  287.                             ATTR_GADGET, sizeof(struct GadgetObject), NULL,
  288.                             TAG_END
  289.                         };
  290.  
  291. METHOD_TAG gadMethods[] =
  292.                         {
  293.                            {
  294.                               METH_INIT,
  295.                               NULL, NULL,
  296.                               INVOKE_SYNC,
  297.                               METH_FLAG_OBJECT, 0,
  298.                               GadgTOpenMethod, REF_GadgTOpenMethod
  299.                            },
  300.                            {
  301.                               METH_GADGET_CHANGE,
  302.                               NULL, NULL,
  303.                               INVOKE_SYNC,
  304.                               METH_FLAG_OBJECT, 0,
  305.                               (METHODFUNCTYPE)GadgTChangeMethod,
  306.                                  REF_GadgTChangeMethod
  307.                            },
  308.                            TAG_END
  309.                         };
  310.  
  311.  
  312. /*
  313.  * ==========================================================================
  314.  * =                                                                        =
  315.  * =           Class definition for asl objects.                            =
  316.  * =                                                                        =
  317.  * ==========================================================================
  318.  */
  319.  
  320. ATTRIBUTE_TAG aslAttrs[] =
  321.                         {
  322.                             ATTR_ASLREQUEST, sizeof(struct AslRequest), NULL,
  323.                             TAG_END
  324.                         };
  325.  
  326. extern ARGUMENT_TAG REF_AslOpenMethod[],
  327.                   REF_AslBeginMethod[],
  328.                   REF_AslDoneMethod[];
  329.  
  330. void *AslOpenMethod(METHOD_ARGS, OBJECT window,
  331.                                  char *name,
  332.                                  OBJECT out_object,
  333.                                  char *out_method,
  334.                                  long aslType,
  335.                                  struct TagItem *tags);
  336.  
  337. extern void AslBeginMethod(METHOD_ARGS, struct TagItem *);
  338. extern void AslLaunchMethod(METHOD_ARGS, struct TagItem *);
  339. extern void AslDoneMethod(METHOD_ARGS, long);
  340. extern void AslRemoveMethod(METHOD_ARGS);
  341. extern void AslDestroyMethod(METHOD_ARGS);
  342.  
  343. METHOD_TAG aslMethods[] =
  344.                         {
  345.                            {
  346.                               METH_INIT,
  347.                               NULL, NULL,
  348.                               INVOKE_SYNC,
  349.                               METH_FLAG_OBJECT, 0,
  350.                               AslOpenMethod, REF_AslOpenMethod
  351.                            },
  352.                            {
  353.                               METH_REMOVE,
  354.                               NULL, NULL,
  355.                               INVOKE_SYNC,
  356.                               METH_FLAG_OBJECT, 0,
  357.                               (METHODFUNCTYPE)AslRemoveMethod, NULL
  358.                            },
  359.                            {
  360.                               METH_DESTROY,
  361.                               NULL, NULL,
  362.                               INVOKE_CALL,
  363.                               METH_FLAG_OBJECT, 0,
  364.                               (METHODFUNCTYPE)AslDestroyMethod, NULL
  365.                            },
  366. #define SET_ASL_LAUNCH 3
  367.                            {
  368.                               METH_ASL_LAUNCH,
  369.                               NULL, NULL,
  370.                               INVOKE_FORCE_ASYNC,
  371.                               METH_FLAG_CLASS, 0,
  372.                               (METHODFUNCTYPE)AslLaunchMethod,
  373.                                  REF_AslBeginMethod
  374.                            },
  375.                            {
  376.                               METH_ASL_BEGIN,
  377.                               NULL, NULL,
  378.                               INVOKE_CALL,
  379.                               METH_FLAG_OBJECT, 0,
  380.                               (METHODFUNCTYPE)AslBeginMethod,
  381.                                  REF_AslBeginMethod
  382.                            },
  383.                            {
  384.                               METH_ASL_DONE,
  385.                               NULL, NULL,
  386.                               INVOKE_SYNC,
  387.                               METH_FLAG_OBJECT, 0,
  388.                               (METHODFUNCTYPE)AslDoneMethod,
  389.                                  REF_AslDoneMethod
  390.                            },
  391.                            TAG_END
  392.                         };
  393.  
  394.  
  395. /*
  396.  * ==========================================================================
  397.  * =                                                                        =
  398.  * =                 Initialize these classes                               =
  399.  * =                                                                        =
  400.  * ==========================================================================
  401.  */
  402.  
  403. void geta4(void);
  404.  
  405. BOOL InitGUISystem(void)
  406. {
  407.    OBJECT guiTask;
  408.    CLASS  aslProcClass;
  409.    BOOL   success;
  410.  
  411.    SetupMethodTags(guiProcMethods, (void *)-1, (void *)-1);
  412.    SetupMethodTags(aslProcMethods, (void *)-1, (void *)-1);
  413.  
  414.    /*
  415.     * Create the guiProcess CLass.
  416.     */
  417.    success = AddAutoResource(NULL,CreateSubClass(NULL,
  418.                                                  PROCESS_CLASS,
  419.                                                  META_CLASS,
  420.                                                  GuiProcClassName,
  421.                                                  NULL,
  422.                                                  guiProcAttrs,
  423.                                                  guiProcMethods,
  424.                                                  METHOD_END),
  425.                              GuiProcClassName);
  426.  
  427.    /*
  428.     * Create the aslProcess CLass.
  429.     */
  430.    success &= AddAutoResource(NULL,
  431.                               aslProcClass = (CLASS)
  432.                                        UseObject(
  433.                                           CreateSubClass(NULL,
  434.                                                    GuiProcClassName,
  435.                                                    META_CLASS,
  436.                                                    AslProcClassName,
  437.                                                    NULL,
  438.                                                    NULL,
  439.                                                    aslProcMethods,
  440.                                                    METHOD_END)),
  441.                               AslProcClassName);
  442.  
  443.    /*
  444.     * Create the guiTask
  445.     */
  446.    {
  447.       struct TagItem tag[4];
  448.  
  449.       tag[0].ti_Tag = NP_Priority;
  450.       tag[0].ti_Data = 1;
  451.       tag[1].ti_Tag = NP_StackSize;
  452.       tag[1].ti_Data = 6000;
  453.       tag[2].ti_Tag = NP_Output;
  454.       tag[2].ti_Data = (ULONG)Open("CONSOLE:", MODE_OLDFILE);
  455.       tag[3].ti_Tag = TAG_END;
  456.  
  457.       guiTask = CreateInstance(NULL,
  458.                                GuiProcClassName,
  459.                                META_CLASS,
  460.                                GuiTaskName,
  461.                                FindTask(NULL)->tc_UserData,
  462.                                NULL,
  463.                                tag,
  464.                                METHOD_END);
  465.  
  466.       if (tag[2].ti_Tag != TAG_IGNORE)
  467.          Close(tag[2].ti_Data);
  468.    }
  469.  
  470.    SetupMethodTags(guiMethods, guiTask, (void *)-1);
  471.    SetupMethodTags(winMethods, guiTask, (void *)-1);
  472.    SetupMethodTags(gadMethods, guiTask, (void *)-1);
  473.    SetupMethodTags(aslMethods, guiTask, (void *)-1);
  474.  
  475.    aslMethods[SET_ASL_LAUNCH].mtag_procObject = aslProcClass;
  476.  
  477.    success &= AddAutoResource(NULL,
  478.                               CreateSubClass(NULL,
  479.                                              ROOT_CLASS,
  480.                                              META_CLASS,
  481.                                              GuiClassName,
  482.                                              NULL,
  483.                                              guiAttrs,
  484.                                              guiMethods,
  485.                                              METHOD_END),
  486.                               GuiClassName);
  487.  
  488.    success &= AddAutoResource(NULL,
  489.                               CreateSubClass(NULL,
  490.                                              GuiClassName,
  491.                                              META_CLASS,
  492.                                              WindowClassName,
  493.                                              NULL,
  494.                                              winAttrs,
  495.                                              winMethods,
  496.                                              METHOD_END),
  497.                               WindowClassName);
  498.  
  499.    success &= AddAutoResource(NULL,
  500.                               CreateSubClass(NULL,
  501.                                              GuiClassName,
  502.                                              META_CLASS,
  503.                                              GadgTClassName,
  504.                                              NULL,
  505.                                              gadAttrs,
  506.                                              gadMethods,
  507.                                              METHOD_END),
  508.                               GadgTClassName);
  509.  
  510.    success &= AddAutoResource(NULL,
  511.                               CreateSubClass(NULL,
  512.                                              GuiClassName,
  513.                                              META_CLASS,
  514.                                              AslClassName,
  515.                                              NULL,
  516.                                              aslAttrs,
  517.                                              aslMethods,
  518.                                              METHOD_END),
  519.                               AslClassName);
  520.  
  521.    success &= AddAutoResource(NULL, guiTask, GuiTaskName);
  522.  
  523.    DropObject(aslProcClass);
  524.    return success;
  525. }
  526.  
  527. /*
  528.  ==========================================================================
  529.                            gui task
  530.  ==========================================================================
  531.  */
  532.  
  533. /*
  534.  * First, define the GUI Process Class
  535.  */
  536. void __saveds *AssociateGuiProcObject(METHOD_ARGS, char *name)
  537. {
  538.    struct GuiProcess *gui = FindAttribute(object, ATTR_GUIPROCESS);
  539.  
  540.    if (IntuitionBase = OpenLibrary("intuition.library", 36))
  541.    {
  542.       if (GadToolsBase = OpenLibrary("gadtools.library", 36))
  543.       {
  544.          if (UtilityBase = OpenLibrary("utility.library", 36))
  545.          {
  546.             if (AslBase = OpenLibrary("asl.library", 36))
  547.             {
  548.                if (gui->guip_port = CreateMsgPort())
  549.                {
  550.                   if (DiskfontBase = OpenLibrary("diskfont.library", 0))
  551.                   {
  552.                      if (GfxBase = OpenLibrary("graphics.library", 0))
  553.                      {
  554.                         if (tf = OpenDiskFont(&ta))
  555.                         {
  556.                            if (CallSuper())
  557.                               return object;
  558.  
  559.                            CloseFont(tf);
  560.                         }
  561.                         CloseLibrary(GfxBase);
  562.                      }
  563.                      CloseLibrary(DiskfontBase);
  564.                   }
  565.                   DeleteMsgPort(gui->guip_port);
  566.                }
  567.                CloseLibrary(AslBase);
  568.             }
  569.             CloseLibrary(UtilityBase);
  570.          }
  571.          CloseLibrary(GadToolsBase);
  572.       }
  573.       CloseLibrary(IntuitionBase);
  574.    }
  575.    return NULL;
  576. }
  577.  
  578. void __saveds HandleGuiProcObject(METHOD_ARGS)
  579. {
  580.    struct ShadowProcess *sp = FindAttribute(object, ATTR_SHADOWPROCESS);
  581.    struct GuiProcess *gui = FindAttribute(object, ATTR_GUIPROCESS);
  582.    struct IPCMessage *msg2;
  583.    struct IntuiMessage *intui;
  584.    ULONG signals;
  585.  
  586.  
  587.    while(TRUE)
  588.    {
  589.       signals = Wait( SigBitIPCPort(sp->sp_port) |
  590.                       SigBitIPCPort(sp->sp_replyPort) |
  591.                       (1L << gui->guip_port->mp_SigBit) |
  592.                       SIGBREAKF_CTRL_C);
  593.  
  594.       while(msg2 = GetIPCMessage(sp->sp_port))
  595.          ParseShadowMessage(msg2, SHADOW_RETURN_MSG_NEVER);
  596.  
  597.       while(msg2 = GetIPCMessage(sp->sp_replyPort))
  598.          JunkIPCMessage(msg2);
  599.  
  600.       while(intui = GT_GetIMsg(gui->guip_port))
  601.          HandleIntuiMessage(intui);
  602.  
  603.       if (signals & SIGBREAKF_CTRL_C)
  604.          if (sp->sp_flags & SHADOW_PROC_FLAGS_DESTROYED)
  605.             break;
  606.    }
  607. }
  608.  
  609. void __saveds DisGuiProcObject(METHOD_ARGS)
  610. {
  611.    struct GuiProcess *gui = FindAttribute(object, ATTR_GUIPROCESS);
  612.  
  613.    CloseFont(tf);
  614.    CloseLibrary(DiskfontBase);
  615.    CloseLibrary(GfxBase);
  616.    DeleteMsgPort(gui->guip_port);
  617.  
  618.    CloseLibrary(AslBase);
  619.    CloseLibrary(UtilityBase);
  620.    CloseLibrary(GadToolsBase);
  621.    CloseLibrary(IntuitionBase);
  622.    CallSuper();
  623. }
  624.  
  625.  
  626. ARGUMENT_TAG REF_InitAslProcObject[] = {
  627.                                        'JSTR', 4, 0,
  628.                                        'JOBJ', 4, 0,
  629.                                        'SEMF', 4, 0,
  630.                                        'TAGL', 4, sizeof(struct TagItem),
  631.                                        TAG_END, SHADOW_RETURN_OBJECT
  632.                                      };
  633.  
  634. void __saveds *InitAslProcObject(METHOD_ARGS, char *name,
  635.                                              OBJECT junk,
  636.                                              struct SignalSemaphore *semJunk,
  637.                                              struct TagItem *tags)
  638. {
  639.    struct TagItem lTags[4];
  640.  
  641.    lTags[0].ti_Tag = NP_Priority;
  642.    lTags[0].ti_Data = 0;
  643.    lTags[1].ti_Tag = NP_StackSize;
  644.    lTags[1].ti_Data = 6000;
  645.    lTags[2].ti_Tag = NP_Output;
  646.    lTags[2].ti_Data = (ULONG)Open("CONSOLE:", MODE_OLDFILE);
  647.    lTags[3].ti_Tag = TAG_MORE;
  648.    lTags[3].ti_Data = (ULONG)tags;
  649.  
  650.    ResetPtr(tags, lTags);
  651.  
  652.    if (!CallSuper())
  653.    {
  654.       Close(lTags[2].ti_Data);
  655.       return NULL;
  656.    }
  657.    return object;
  658. }
  659.  
  660.  
  661.  
  662. /*
  663.  *
  664.  * GUI CLASS METHODS
  665.  *
  666.  */
  667. ARGUMENT_TAG REF_GuiInitMethod[] = {
  668.                                     {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  669.                                     {'JSTR', sizeof(char *), 0},
  670.                                     {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  671.                                     {'JSTR', sizeof(char *), 0},
  672.                                     {TAG_END, SHADOW_RETURN_OBJECT, 0}
  673.                                  };
  674.  
  675. void *GuiInitMethod(METHOD_ARGS, OBJECT parent,
  676.                                  char *name,
  677.                                  OBJECT out_object,
  678.                                  char *out_method)
  679. {
  680.    W_AVLTREE Wtree;
  681.    struct GUIStruct *gui;
  682.    struct OutputStruct *io;
  683.  
  684.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  685.    gui->gui_parent = parent;
  686.  
  687.    if (parent)
  688.       Wtree = FindAttribute(parent, ATTR_GUICHILDREN);
  689.  
  690.    io = FindAttribute(object, ATTR_GUIOUTPUT);
  691.    io->out_object = out_object;
  692.  
  693.    UseObject(object);
  694.    UseObject(parent);
  695.    UseObject(out_object);
  696.  
  697.    if (!name || (name = UseString(name)))
  698.    {
  699.       gui->gui_moniker = name;
  700.       if (!out_method || (out_method = UseString(out_method)))
  701.       {
  702.          io->out_method = out_method;
  703.          if (!parent || AddWatchedTreeStringNode(Wtree, object, name))
  704.          {
  705.             if(DoSuperShadow(object, class, MethodID, METHOD_END))
  706.             {
  707.  
  708.                DropObject(object);
  709.                return object;
  710.             }
  711.             if (parent) RemoveWatchedTreeStringNode(Wtree, object, name);
  712.          }
  713.          DropString(out_method);
  714.       }
  715.       DropString(name);
  716.    }
  717.    DropObject(object);
  718.    return NULL;
  719. }
  720.  
  721. /*
  722.  * Watch the semaphores!
  723.  */
  724.  
  725. void GuiRemoveMethod(METHOD_ARGS)
  726. {
  727.    struct GUIStruct *gui;
  728.    struct OutputStruct *io;
  729.    W_AVLTREE children;
  730.    OBJECT    parent;
  731.  
  732.    DropObject(ReplaceObject(&__GlobalFocus, NULL, object));
  733.  
  734.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  735.    io = FindAttribute(object, ATTR_GUIOUTPUT);
  736.  
  737.    PSem(object, SSEM_LOCK);
  738.  
  739.    DropObject(io->out_object);
  740.    QuickDropString(io->out_method);
  741.  
  742.    parent = gui->gui_parent;
  743.    gui->gui_parent = io->out_object = NULL;
  744.    io->out_method = NULL;
  745.  
  746.    VSem(object);
  747.  
  748.    children = FindAttribute(object, ATTR_GUICHILDREN);
  749.    PSem(&children->wv_value, SSEM_READ);
  750.    while(children->wv_value)
  751.    {
  752.       OBJECT gadgetObject;
  753.  
  754.       gadgetObject = UseObject((void *)children->wv_value->bn_value);
  755.       VSem(&children->wv_value);
  756.       DoShadow(gadgetObject, NULL, METH_REMOVE, METHOD_END);
  757.       DropObject(gadgetObject);
  758.       PSem(&children->wv_value, SSEM_READ);
  759.    }
  760.  
  761.    VSem(&children->wv_value);
  762.  
  763.    /*
  764.     * remove object from parent list.
  765.     */
  766.    if (parent)
  767.    {
  768.       /*
  769.        * Ignore misnomer, please.
  770.        * Actually, fellow sblings.
  771.        */
  772.       children = FindAttribute(parent, ATTR_GUICHILDREN);
  773.       RemoveWatchedTreeStringNode(children, object, gui->gui_moniker);
  774.    }
  775.  
  776.    CallSuper();
  777.    DropObject(parent);
  778. }
  779.  
  780. void GuiDestroyMethod(METHOD_ARGS)
  781. {
  782.    struct GUIStruct *gui;
  783.  
  784.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  785.    QuickDropString(gui->gui_moniker);
  786.    CallSuper();
  787. }
  788.  
  789. ARGUMENT_TAG REF_GuiGrabFocus[] = {'flag', 4, 0, TAG_END};
  790.  
  791. void GuiGrabFocus(METHOD_ARGS, long flag)
  792. {
  793.    DropObject(SetObject(&__GlobalFocus, (flag)?UseObject(object):NULL));
  794. }
  795.  
  796. /*
  797.  * ARGUMENT_TAG for external use!
  798.  */
  799.  
  800. ARGUMENT_TAG REF_GuiStateNotify[] = {'INTU', 4, sizeof(struct GuiIntuiMsg),
  801.                                    'JOBJ', 4, SHADOW_OBJECT,
  802.                                    TAG_END};
  803. void GuiStateNotify(METHOD_ARGS, struct GuiIntuiMsg *info, OBJECT window)
  804. {
  805.    struct OutputStruct  *out;
  806.    OBJECT obj2;
  807.  
  808.    /*
  809.     * Change the focus as required.
  810.     */
  811.    if (info)
  812.       switch(info->gii_Class)
  813.       {
  814.          case MOUSEBUTTONS:
  815.              if (info->gii_Code & IECODE_UP_PREFIX)
  816.                DropObject(ReplaceObject(&__GlobalFocus, NULL, object));
  817.             else
  818.                DoShadow(object, NULL, METH_GUI_FOCUS,
  819.                                           (void *)TRUE,
  820.                                           METHOD_END);
  821.             break;
  822.          case INACTIVEWINDOW:
  823.             DropObject(ReplaceObject(&__GlobalFocus, NULL, object));
  824.             break;
  825.       }
  826.    out = FindAttribute(object, ATTR_GUIOUTPUT);
  827.    if (!(obj2 = GetObject(&out->out_object)))
  828.       return;
  829.  
  830.    DoShadow(obj2, NULL, out->out_method, info, window, object, METHOD_END);
  831.  
  832.    DropObject(obj2);
  833. }
  834.  
  835. /*
  836.  *
  837.  * WINDOW CLASS METHODS
  838.  *
  839.  */
  840.  
  841. BOOL CalculateWindowPosition(struct WindowLocation *wloc,
  842.                              struct TagItem *tag,
  843.                              char *name)
  844. {
  845.    struct WindowLocation wl;
  846.    struct Screen *screen;
  847.    struct Window *win;
  848.    ULONG ibaseLock, recurse, origRecurse;
  849.    USHORT left, top, height, width;
  850.  
  851.    if (!wloc)
  852.    {
  853.       return TRUE;
  854.    }
  855.  
  856.    if (!(screen = LockPubScreen((char *)GetTagData(WA_PubScreenName,
  857.                                                    NULL,
  858.                                                    tag))))
  859.    {
  860.       return FALSE;
  861.    }
  862.  
  863.    wl = *wloc;
  864.  
  865.    /*
  866.     * Setup the tag's ti_Tag values.
  867.     */
  868.  
  869.    tag[0].ti_Tag = WA_Left;
  870.    tag[1].ti_Tag = WA_Top;
  871.    tag[2].ti_Tag = (wl.wl_width & WLO_Border)?WA_InnerWidth:WA_Width;
  872.    tag[3].ti_Tag = (wl.wl_height & WLO_Border)?WA_InnerHeight:WA_Height;
  873.  
  874.    /*
  875.     * Take care of screen-percent stuff.  Neat huh?
  876.     */
  877.  
  878.    if (wl.wl_left & WLO_Percent)
  879.    {
  880.       wl.wl_left &= 0xffff0000;
  881.       wl.wl_left |= (screen->Width * (wl.wl_left & 0xffff))/0xffff;
  882.    }
  883.    if (wl.wl_width & WLO_Percent)
  884.       wl.wl_width = (screen->Width * (wl.wl_width & 0xffff))/0xffff;
  885.  
  886.    if (wl.wl_left & WLO_UnderMouse)
  887.       wl.wl_left = screen->MouseX;
  888.  
  889.    /*
  890.     * Left-Width border check.
  891.     */
  892.    if ((wl.wl_left & 0xffff) + (wl.wl_width & 0xffff) > screen->Width)
  893.    {
  894.       wl.wl_left = max(0, screen->Width - (wl.wl_width & 0xffff));
  895.    }
  896.  
  897.    /*
  898.     * Top edge screen-percents.
  899.     */
  900.    if (wl.wl_top & WLO_Percent)
  901.    {
  902.       wl.wl_top &= 0xffff0000;
  903.       wl.wl_top |= (screen->Height * (wl.wl_top & 0xffff))/0xffff;
  904.    }
  905.    if (wl.wl_height & WLO_Percent)
  906.       wl.wl_height = (screen->Height * (wl.wl_height & 0xffff))/0xffff;
  907.  
  908.    if (wl.wl_top & WLO_UnderMouse)
  909.       wl.wl_top = screen->MouseY;
  910.  
  911.    /*
  912.     * Top-Height border check.
  913.     */
  914.    if ((wl.wl_top & 0xffff) + (wl.wl_height & 0xffff) > screen->Height)
  915.    {
  916.       wl.wl_top = max(0, screen->Height - (wl.wl_height & 0xffff));
  917.    }
  918.  
  919.    /*
  920.     * So, now we have the starting positions.
  921.     * We need to search the screen for a better, optimal location.
  922.     */
  923.  
  924.    ibaseLock = LockIBase(0L);
  925.  
  926.    height = width = 0;
  927.    left = (wl.wl_left &= 0xffff);
  928.    top = (wl.wl_top &= 0xffff);
  929.    wl.wl_width &= 0xffff;
  930.    wl.wl_height &= 0xffff;
  931.  
  932.    name = UseString(name);
  933.  
  934.    /*
  935.     * Any other windows of the same name around here?
  936.     * We will use their height to pre-calculate the width/height.
  937.     */
  938.    for(win = screen->FirstWindow; win; win= win->NextWindow)
  939.    {
  940.       if (win->Title == name || win->ScreenTitle == name)
  941.       {
  942.          height = win->Height;
  943.          width = win->Width;
  944.          if (!wl.wl_width)
  945.          {
  946.             wl.wl_width = width;
  947.             tag[2].ti_Tag = WA_Width;
  948.          }
  949.          if (!wl.wl_height)
  950.          {
  951.             wl.wl_height = height;
  952.             tag[3].ti_Tag = WA_Height;
  953.          }
  954.          break;
  955.       }
  956.    }
  957.  
  958.  
  959.    if (!(wloc->wl_flags & WLO_NoAuto))
  960.    {
  961.  
  962.       recurse = origRecurse = 0;
  963.       for(win = screen->FirstWindow; win; win = (win)?win->NextWindow:
  964.                                                 screen->FirstWindow)
  965.       {
  966.          ULONG xInc, yInc, xInc2, yInc2;
  967.  
  968.          /*
  969.           * First, is the increment as a percentage of the window
  970.           *  size, or as straight pixels.  The window size is then
  971.           *  either the win->[Width|Height] -OR- without the borders,
  972.           *  depending on whether the BORDER bit is set.  This way you
  973.           *  can skip the border PLUS a remaining portion of the window.
  974.           */
  975.          if (wl.wl_xInc & WLO_Percent)
  976.          {
  977.             if (wl.wl_xInc & WLO_Border)
  978.                xInc = (((win->Width - win->BorderLeft) *
  979.                         (wl.wl_xInc & 0xffff))/0xffff);
  980.             else
  981.                xInc = ((win->Width * (wl.wl_xInc & 0xffff))/0xffff);
  982.          } else
  983.             xInc = (wl.wl_xInc & 0xffff);
  984.  
  985.          if (wl.wl_yInc & WLO_Percent)
  986.          {
  987.             if (wl.wl_yInc & WLO_Border)
  988.                yInc = (((win->Height - win->BorderTop) *
  989.                         (wl.wl_yInc & 0xffff))/0xffff);
  990.             else
  991.                yInc = ((win->Height * (wl.wl_yInc & 0xffff))/0xffff);
  992.          } else
  993.             yInc = (wl.wl_yInc & 0xffff);
  994.  
  995.          /*
  996.           * This is the increment for RE_TILE, as well as a check
  997.           *  to verify that the window doesn't encroach on another window
  998.           *  from the left.  The above checks if the window itself is
  999.           *  encroached from the left.
  1000.           *
  1001.           * The border size is the same for all windows, so....
  1002.           */
  1003.          if (wl.wl_xInc & WLO_Percent)
  1004.          {
  1005.             if (wl.wl_xInc & WLO_Border)
  1006.                xInc2 = (((width - win->BorderLeft) *
  1007.                          (wl.wl_xInc & 0xffff))/0xffff);
  1008.             else
  1009.                xInc2 = ((width * (wl.wl_xInc & 0xffff))/0xffff);
  1010.          } else
  1011.             xInc2 = (wl.wl_xInc & 0xffff);
  1012.  
  1013.          if (wl.wl_yInc & WLO_Percent)
  1014.          {
  1015.             if (wl.wl_yInc & WLO_Border)
  1016.                yInc2 = (((height - win->BorderTop) *
  1017.                          (wl.wl_yInc & 0xffff))/0xffff);
  1018.             else
  1019.                yInc2 = ((height * (wl.wl_yInc & 0xffff))/0xffff);
  1020.          } else
  1021.             yInc2 = (wl.wl_yInc & 0xffff);
  1022.  
  1023.          /*
  1024.           * Add in the border offsets.
  1025.           */
  1026.          if (wl.wl_xInc & WLO_Border)
  1027.             xInc += win->BorderLeft;
  1028.          if (wl.wl_yInc & WLO_Border)
  1029.             yInc += win->BorderTop;
  1030.  
  1031.          if (wl.wl_xInc & WLO_Border)
  1032.             xInc2 += win->BorderLeft;
  1033.          if (wl.wl_yInc & WLO_Border)
  1034.             yInc2 += win->BorderTop;
  1035.  
  1036.          /*
  1037.           * Is window either:
  1038.           *    a) encroached on by another window or
  1039.           *    b) encraching ON another window.
  1040.           *
  1041.           * b) calculation won't work for the first parameter window
  1042.           *    of a module....
  1043.           */
  1044.          if ((left - win->LeftEdge < ((xInc)?xInc:1) &&
  1045.               left - win->LeftEdge >= 0 &&
  1046.               top - win->TopEdge < ((yInc)?yInc:1) &&
  1047.               top - win->TopEdge >= 0)          ||
  1048.              (win->LeftEdge - left < ((xInc2)?xInc2:1) &&
  1049.               win->LeftEdge - left >= 0 &&
  1050.               win->TopEdge - top < ((yInc2)?yInc2:1) &&
  1051.               win->TopEdge - top >= 0))
  1052.          {
  1053.             BOOL changed = FALSE;
  1054.  
  1055.             if (recurse)
  1056.             {
  1057.                --recurse;
  1058.                continue;
  1059.             }
  1060.  
  1061.             if (!( ( (wl.wl_flags & WLO_TileHoriz) &&
  1062.                      (wl.wl_flags & WLO_ReTile)     ) ||
  1063.                    ( (wl.wl_flags & WLO_TileVert) &&
  1064.                     !(wl.wl_flags & WLO_TileHoriz) &&
  1065.                     !(wl.wl_flags & WLO_ReTile)     )) &&
  1066.                 !(wloc->wl_left & WLO_UnderMouse))
  1067.             {
  1068.                if (wl.wl_flags & WLO_ReTile)
  1069.                   left += ((xInc2)?xInc2:xInc);
  1070.                else
  1071.                   left = win->LeftEdge + xInc;
  1072.                changed = TRUE;
  1073.             }
  1074.             if (!( ( (wl.wl_flags & WLO_TileVert ) &&
  1075.                      (wl.wl_flags & WLO_ReTile)     ) ||
  1076.                    ( (wl.wl_flags & WLO_TileHoriz) &&
  1077.                     !(wl.wl_flags & WLO_TileVert ) &&
  1078.                     !(wl.wl_flags & WLO_ReTile)     )) &&
  1079.                 !(wloc->wl_top & WLO_UnderMouse))
  1080.             {
  1081.                if (wl.wl_flags & WLO_ReTile)
  1082.                   top += ((yInc2)?yInc2:yInc);
  1083.                else
  1084.                   top = win->TopEdge + yInc;
  1085.                changed = TRUE;
  1086.             }
  1087.  
  1088.             if (!changed && !(wl.wl_flags & WLO_ReTile))
  1089.                /*
  1090.                 * Caught in non-update loop!
  1091.                 */
  1092.                break;
  1093.  
  1094.             wl.wl_flags &= ~WLO_ReTile;
  1095.  
  1096.             /*
  1097.              * Double border problem?
  1098.              */
  1099.             if ((top + ((height)?height:win->Height) > screen->Height) &&
  1100.                 (left + ((width)?width:win->Width) > screen->Width))
  1101.             {
  1102.                top = wl.wl_top;
  1103.                left = wl.wl_left & 0xffff;
  1104.                if (top == wl.wl_top |
  1105.                    left == wl.wl_left)
  1106.                   break;
  1107.                origRecurse++;
  1108.                wl.wl_flags &= ~(WLO_ResetHoriz | WLO_ResetVert);
  1109.             }
  1110.  
  1111.             /*
  1112.              * Border collision check.
  1113.              */
  1114.             if (top + ((height)?height:win->Height) > screen->Height)
  1115.             {
  1116.                if (top == wl.wl_top)
  1117.                   break;
  1118.  
  1119.                top = wl.wl_top;
  1120.                wl.wl_flags |= WLO_ResetVert;
  1121.                if (wl.wl_flags & WLO_TileVert)
  1122.                   wl.wl_flags |= WLO_ReTile;
  1123.  
  1124.                if (wl.wl_flags & WLO_ResetHoriz ||
  1125.                    !wl.wl_xInc ||
  1126.                    (wloc->wl_left & WLO_UnderMouse))
  1127.                {
  1128.                   origRecurse++;
  1129.                   wl.wl_flags &= ~(WLO_ResetHoriz | WLO_ResetVert);
  1130.                }
  1131.             }
  1132.  
  1133.             if (left + ((width)?width:win->Width) > screen->Width)
  1134.             {
  1135.                if (left == wl.wl_left)
  1136.                   break;
  1137.  
  1138.                left = wl.wl_left;
  1139.                wl.wl_flags |= WLO_ResetHoriz;
  1140.                if (wl.wl_flags & WLO_TileHoriz)
  1141.                   wl.wl_flags |= WLO_ReTile;
  1142.                if (wl.wl_flags & WLO_ResetVert ||
  1143.                    !wl.wl_yInc ||
  1144.                    (wloc->wl_top & WLO_UnderMouse))
  1145.                {
  1146.                   origRecurse++;
  1147.                   wl.wl_flags &= ~(WLO_ResetHoriz | WLO_ResetVert);
  1148.                }
  1149.             }
  1150.  
  1151.             recurse = origRecurse;
  1152.             win = NULL;
  1153.          }
  1154.       }
  1155.    }
  1156.  
  1157.    tag[0].ti_Data = left;
  1158.    tag[1].ti_Data = top;
  1159.    tag[2].ti_Data = (wl.wl_width)?wl.wl_width:1;
  1160.    tag[3].ti_Data = (wl.wl_height)?wl.wl_height:1;
  1161.  
  1162.    UnlockIBase(ibaseLock);
  1163.    QuickDropString(name);
  1164.    UnlockPubScreen(NULL, screen);
  1165.  
  1166.    return TRUE;
  1167. }
  1168.  
  1169. /*
  1170.  * METH_INIT
  1171.  */
  1172. ARGUMENT_TAG  REF_WinOpenMethod[] = {
  1173.                                      {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  1174.                                      {'JSTR', sizeof(char *), 0},
  1175.                                      {'JOBJ', sizeof(void *), SHADOW_OBJECT},
  1176.                                      {'JSTR', sizeof(char *), 0},
  1177.                                      {'TAGL', sizeof(void *),
  1178.                                               sizeof(struct TagItem)},
  1179.                                      {'JOBJ', sizeof(OBJECT), SHADOW_OBJECT},
  1180.                                      {TAG_END, SHADOW_RETURN_OBJECT, 0}
  1181.                                   };
  1182.  
  1183. void *WinOpenMethod(METHOD_ARGS, OBJECT parent,
  1184.                                  char *name,
  1185.                                  OBJECT out_object,
  1186.                                  char *out_method,
  1187.                                  struct TagItem *tags,
  1188.                                  OBJECT wlObject)
  1189. {
  1190.    struct WindowObject *wobj;
  1191.    struct WindowLocation *wl;
  1192.    struct TagItem tag[5];
  1193.  
  1194.    tag[0].ti_Tag = tag[4].ti_Tag = TAG_MORE;
  1195.    tag[0].ti_Data = tag[4].ti_Data = (ULONG)tags;
  1196.  
  1197.    if (!CalculateWindowPosition(wl = (void *)GetTagData(WLO_Location,
  1198.                                                         NULL,
  1199.                                                         tags),
  1200.                                 tag,
  1201.                                 name))
  1202.    {
  1203.       DropObject(UseObject(object));
  1204.       return NULL;
  1205.    }
  1206.  
  1207.    UseObject(object);
  1208.    wobj = FindAttribute(object, ATTR_WINDOW);
  1209.    name = UseString(name);
  1210.  
  1211.    if (wobj->wo_window = OpenWindowTags(NULL, WA_Flags, 0xf,
  1212.                                               WA_Title, name,
  1213.                                               TAG_MORE, tag))
  1214.    {
  1215.       struct GuiProcess *gui;
  1216.  
  1217.       gui = FindAttribute(FindTask(NULL)->tc_UserData, ATTR_GUIPROCESS);
  1218.  
  1219.       wobj->wo_window->UserPort = gui->guip_port;
  1220.       wobj->wo_window->UserData = (void *)object;
  1221.  
  1222.       /*
  1223.        * Would require V37 to check ModifyIDCMP!
  1224.        */
  1225.  
  1226.       ModifyIDCMP(wobj->wo_window, LISTVIEWIDCMP | CLOSEWINDOW |
  1227.                                    REFRESHWINDOW | INACTIVEWINDOW |
  1228.                                    ACTIVEWINDOW);
  1229.  
  1230.       {
  1231.          if (wobj->wo_vi = GetVisualInfo(wobj->wo_window->WScreen, TAG_END))
  1232.          {
  1233.             if (wobj->wo_lastGadget = CreateContext(&wobj->wo_rootGadget))
  1234.             {
  1235.                AddGList(wobj->wo_window, wobj->wo_rootGadget, -1, -1, NULL);
  1236.  
  1237.                /*
  1238.                 * Force tags to NULL -- ick, I hate optimizers.
  1239.                 */
  1240.  
  1241.                ForceMethodEnd(out_method);
  1242.  
  1243.                if (CallSuper())
  1244.                {
  1245.                   /*
  1246.                    * Used twice, once for return, once in window structure.
  1247.                    */
  1248.  
  1249.                   /*
  1250.                    * Name is in superClass under gui->gui_moniker
  1251.                    */
  1252.                   DropString(name);
  1253.                   wobj->wo_wl = wl;
  1254.  
  1255.                   if (wl && (wl->wl_flags & WLO_Backstore) && wlObject)
  1256.                   {
  1257.                      wl->wl_localLeft = wobj->wo_window->LeftEdge;
  1258.                      wl->wl_localTop = wobj->wo_window->TopEdge;
  1259.                      wl->wl_localWidth = wobj->wo_window->Width;;
  1260.                      wl->wl_localHeight = wobj->wo_window->Height;
  1261.                   }
  1262.                   DropObject(SetObject(&wobj->wo_wlObject,
  1263.                                        UseObject(wlObject)));
  1264.                   return object;
  1265.                }
  1266.             }
  1267.          }
  1268.       }
  1269.       DropString(name);
  1270.       DoShadow(object, NULL, METH_WINDOW_CLOSE, METHOD_END);
  1271.       return NULL;
  1272.    }
  1273.    DropString(name);
  1274.    DropObject(object);
  1275.    return NULL;
  1276. }
  1277.  
  1278. void WinDestroyMethod(METHOD_ARGS)
  1279. {
  1280.    struct WindowObject *wobj = FindAttribute(object, ATTR_WINDOW);
  1281.    char *localWindowName = wobj->wo_localWindowName;
  1282.    struct Window *window;
  1283.  
  1284.    if (window = wobj->wo_window)
  1285.    {
  1286.       if (wobj->wo_rootGadget)
  1287.       {
  1288.          FreeGadgets(wobj->wo_rootGadget);
  1289.       }
  1290.       CloseWindow(window);
  1291.    }
  1292.  
  1293.    FreeVisualInfo(wobj->wo_vi);
  1294.  
  1295.    CallSuper();
  1296.  
  1297.    if (localWindowName)
  1298.       FreeMem(localWindowName, strlen(localWindowName) + 1);
  1299. }
  1300.  
  1301. void WinUpdateMethod(METHOD_ARGS)
  1302. {
  1303.    struct WindowObject *wo;
  1304.    struct WindowLocation *wl;
  1305.    OBJECT wlObject;
  1306.  
  1307.    wo = FindAttribute(object, ATTR_WINDOW);
  1308.  
  1309.    /*
  1310.     * Figure out what to do with the location stuff, if anything.
  1311.     */
  1312.    /*
  1313.     * Reset leftedge/topedge if -modified- from original setting set
  1314.     *  NOAUTO!
  1315.     */
  1316.    if ((wlObject = GetObject(&wo->wo_wlObject)) &&
  1317.        (wl = wo->wo_wl) &&
  1318.        (wl->wl_flags & WLO_Backstore))
  1319.    {
  1320.       if (wo->wo_window->LeftEdge != wl->wl_localLeft ||
  1321.           wo->wo_window->TopEdge != wl->wl_localTop   ||
  1322.           wo->wo_window->Width != wl->wl_localWidth   ||
  1323.           wo->wo_window->Height != wl->wl_localHeight)
  1324.       {
  1325.          wl->wl_left = wo->wo_window->LeftEdge;
  1326.          wl->wl_width = wo->wo_window->Width;
  1327.          wl->wl_top = wo->wo_window->TopEdge;
  1328.          wl->wl_height = wo->wo_window->Height;
  1329.          wl->wl_flags |= WLO_NoAuto;
  1330.       }
  1331.    }
  1332.    DropObject(wlObject);
  1333.  
  1334. }
  1335.  
  1336. void WinCloseMethod(METHOD_ARGS)
  1337. {
  1338.    struct WindowObject *wo;
  1339.    struct Window *window;
  1340.  
  1341.    wo = FindAttribute(object, ATTR_WINDOW);
  1342.  
  1343.    /*
  1344.     * Update window locations.
  1345.     */
  1346.    DoShadow(object, NULL, METH_WINDOW_UPDATE, METHOD_END);
  1347.    DropObject(SetObject(&wo->wo_wlObject, NULL));
  1348.  
  1349.    /*
  1350.     * Should remove all child gadgets.
  1351.     */
  1352.  
  1353.    if (window = wo->wo_window)
  1354.    {
  1355.       RemoveGList(window, wo->wo_rootGadget, -1);
  1356.       RemoveWinSafely(window);      /* Unuses object from UserData field */
  1357.    }
  1358.    CallSuper();
  1359. }
  1360.  
  1361. ARGUMENT_TAG REF_MoveWin[] = {'APTR', 4, sizeof(ULONG) * 4, TAG_END};
  1362.  
  1363. void MoveWin(METHOD_ARGS, long *pos)
  1364. {
  1365.    struct WindowObject *wo;
  1366.  
  1367.    if (!pos)
  1368.       return;
  1369.  
  1370.    wo = FindAttribute(object, ATTR_WINDOW);
  1371.    ChangeWindowBox(wo->wo_window, pos[0], pos[1], pos[2], pos[3]);
  1372. }
  1373.  
  1374. ARGUMENT_TAG REF_PreTitleWindow[] = {'JSTR', 4, 0, TAG_END};
  1375.  
  1376. /*
  1377.  * ASYNC, so the return is ignored, but just in case....
  1378.  */
  1379. BOOL PreTitleWindow(METHOD_ARGS, char *string)
  1380. {
  1381.    struct GUIStruct *gui = FindAttribute(object, ATTR_GUISTRUCT);
  1382.    struct WindowObject *wo = FindAttribute(object, ATTR_WINDOW);
  1383.    char *title;
  1384.    int length;
  1385.  
  1386.    if ( (length = strlen(string) + strlen(gui->gui_moniker)) > 250)
  1387.    {
  1388.       return FALSE;
  1389.    }
  1390.    PSem(&wo->wo_localWindowName, SSEM_WRITE);
  1391.    if (wo->wo_localWindowName)
  1392.       FreeMem(wo->wo_localWindowName, strlen(wo->wo_localWindowName) + 1);
  1393.    if (title = wo->wo_localWindowName = AllocMem(length + 4, MEMF_PUBLIC))
  1394.    {
  1395.       strcpy(title, string);
  1396.       strcat(title, " : ");
  1397.       strcat(title, gui->gui_moniker);
  1398.       SetWindowTitles(wo->wo_window, title, (char *)-1);
  1399.       VSem(&wo->wo_localWindowName);
  1400.       return TRUE;
  1401.    }
  1402.  
  1403.    VSem(&wo->wo_localWindowName);
  1404.    return FALSE;
  1405. }
  1406.  
  1407. /*
  1408.  *
  1409.  * GADGT METHODS
  1410.  *
  1411.  */
  1412.  
  1413. ARGUMENT_TAG REF_GadgTOpenMethod[] =
  1414.                                     {
  1415.                                        'JOBJ', sizeof(OBJECT),
  1416.                                                SHADOW_OBJECT,
  1417.                                        'JSTR', sizeof(char *), 0,
  1418.                                        'JOBJ', sizeof(void *),
  1419.                                                SHADOW_OBJECT,
  1420.                                        'JSTR', sizeof(char *), 0,
  1421.                                        'NGAD', sizeof(struct NewGadget *),
  1422.                                                sizeof(struct NewGadget),
  1423.                                        'type', sizeof(long), 0,
  1424.                                        'TAGL', sizeof(void *),
  1425.                                                sizeof(struct TagItem),
  1426.                                        {TAG_END, SHADOW_RETURN_OBJECT, 0}
  1427.                                     };
  1428.  
  1429. void *GadgTOpenMethod(METHOD_ARGS, OBJECT window,
  1430.                                    char *name,
  1431.                                    OBJECT out_object,
  1432.                                    char *out_method,
  1433.                                    struct NewGadget *ng,
  1434.                                    long gadType,
  1435.                                    struct TagItem *tags)
  1436. {
  1437.    struct GadgetObject *gobj;
  1438.    struct WindowObject *windowObj;
  1439.  
  1440.    UseObject(object);
  1441.    if (!window || !ng)
  1442.    {
  1443.       DropObject(object);
  1444.       return NULL;
  1445.    }
  1446.  
  1447.    gobj = FindAttribute(object, ATTR_GADGET);
  1448.    if (!(windowObj = FindAttribute(window, ATTR_WINDOW)))
  1449.    {
  1450.       DropObject(object);
  1451.       return NULL;
  1452.    }
  1453.  
  1454.    ng->ng_TextAttr = &ta;
  1455.    ng->ng_VisualInfo = windowObj->wo_vi;
  1456.    ng->ng_UserData = object;
  1457.    ng->ng_GadgetText = UseString(name);
  1458.    ng->ng_GadgetID = gadType;
  1459.  
  1460.    RemoveGList(windowObj->wo_window, windowObj->wo_rootGadget, -1);
  1461.  
  1462.    if (gobj->go_gadget = CreateGadgetA(gadType, windowObj->wo_lastGadget, ng, tags))
  1463.    {
  1464.       AddGList(windowObj->wo_window, windowObj->wo_rootGadget, -1, -1, NULL);
  1465.  
  1466.       ForceMethodEnd(ng);
  1467.       if (CallSuper())
  1468.       {
  1469.          RefreshGList(windowObj->wo_lastGadget, windowObj->wo_window, NULL, ((UWORD)-1));
  1470.          windowObj->wo_lastGadget = gobj->go_gadget;
  1471.  
  1472.          GT_RefreshWindow(windowObj->wo_window, NULL);
  1473.  
  1474.          /*
  1475.           * name used by superClass, can drop it here.
  1476.           * Otherwise would have to subclass METH_DESTROY, which would suck.
  1477.           */
  1478.          DropString(name);
  1479.          DropObject(object);
  1480.          return object;
  1481.       }
  1482.    } else
  1483.       AddGList(windowObj->wo_window, windowObj->wo_rootGadget, -1, -1, NULL);
  1484.    DropObject(object);
  1485.    return NULL;
  1486. }
  1487.  
  1488. ARGUMENT_TAG REF_GadgTChangeMethod[] =
  1489.                                     {
  1490.                                        'TAGL', sizeof(void *),
  1491.                                                sizeof(struct TagItem),
  1492.                                        TAG_END
  1493.                                     };
  1494. void GadgTChangeMethod(METHOD_ARGS, struct TagItem *tags)
  1495. {
  1496.    struct GadgetObject *gobj;
  1497.    struct GUIStruct *gui;
  1498.    struct WindowObject *windowObj;
  1499.  
  1500.    gobj = FindAttribute(object, ATTR_GADGET);
  1501.    gui = FindAttribute(object, ATTR_GUISTRUCT);
  1502.    windowObj = FindAttribute(gui->gui_parent, ATTR_WINDOW);
  1503.  
  1504.    GT_SetGadgetAttrsA(gobj->go_gadget, windowObj->wo_window, NULL, tags);
  1505. }
  1506.  
  1507. /*
  1508.  *
  1509.  * ASL METHODS
  1510.  *
  1511.  */
  1512.  
  1513. ARGUMENT_TAG REF_AslOpenMethod[] =
  1514.                                     {
  1515.                                        'JOBJ', sizeof(OBJECT),
  1516.                                                SHADOW_OBJECT,
  1517.                                        'JSTR', sizeof(char *), 0,
  1518.                                        'JOBJ', sizeof(void *),
  1519.                                                SHADOW_OBJECT,
  1520.                                        'JSTR', sizeof(char *), 0,
  1521.                                        'type', sizeof(long), 0,
  1522.                                        'TAGL', sizeof(void *),
  1523.                                                sizeof(struct TagItem),
  1524.                                        {TAG_END, SHADOW_RETURN_OBJECT, 0}
  1525.                                     };
  1526.  
  1527. void *AslOpenMethod(METHOD_ARGS, OBJECT window,
  1528.                                  char *name,
  1529.                                  OBJECT out_object,
  1530.                                  char *out_method,
  1531.                                  long gadType,
  1532.                                  struct TagItem *tags)
  1533. {
  1534.    struct AslRequest *aslR;
  1535.    struct WindowObject *windowObj;
  1536.    struct TagItem lTags[10], *t = lTags, *t2;
  1537.  
  1538.    aslR = FindAttribute(object, ATTR_ASLREQUEST);
  1539.  
  1540.    aslR->ar_gadType = gadType;
  1541.  
  1542.    if (!(t2 = FindTagItem(ASL_Window, tags)) &&
  1543.        (windowObj = FindAttribute(window, ATTR_WINDOW)))
  1544.    {
  1545.       t->ti_Tag = ASL_Window,
  1546.       t->ti_Data = (ULONG)windowObj->wo_window;
  1547.       t++;
  1548.    } else if (t2)
  1549.    {
  1550.       struct Window *win;
  1551.  
  1552.       win = (struct Window *)t2->ti_Data;
  1553.       *(OBJECT *)((ULONG)&window) = (OBJECT)win->UserData;
  1554.    }
  1555.  
  1556.    if (!FindTagItem(ASL_Hail, tags))
  1557.    {
  1558.       t->ti_Tag = ASL_Hail;
  1559.       t->ti_Data = (ULONG)UseString(name);
  1560.       t++;
  1561.    } else UseString(name);
  1562.  
  1563.    if (t2 = FindTagItem(ASL_FuncFlags, tags))
  1564.    {
  1565.       t2->ti_Data |=
  1566.          ((gadType == ASL_FileRequest)?FILF_NEWIDCMP:FONF_NEWIDCMP);
  1567.    } else
  1568.    {
  1569.       t->ti_Tag = ASL_FuncFlags;
  1570.       t->ti_Data = (gadType == ASL_FileRequest)?FILF_NEWIDCMP:FONF_NEWIDCMP;
  1571.       t++;
  1572.    }
  1573.  
  1574.    t->ti_Tag = TAG_MORE;
  1575.    t->ti_Data = (ULONG)tags;
  1576.  
  1577.    if (aslR->ar_Requester = AllocAslRequest(gadType, lTags))
  1578.    {
  1579.       ForceMethodEnd(gadType);
  1580.       if (CallSuper())
  1581.       {
  1582.          /*
  1583.           * name used by superClass, can drop it here.
  1584.           * Otherwise would have to subclass METH_DESTROY, which would suck.
  1585.           */
  1586.          DropString(name);
  1587.          aslR->ar_ParentWindow = UseObject(window);
  1588.          return object;
  1589.       }
  1590.       FreeAslRequest(aslR->ar_Requester);
  1591.       aslR->ar_Requester = NULL;
  1592.    }
  1593.    DropString(name);
  1594.    DropObject(UseObject(object));
  1595.    return NULL;
  1596. }
  1597.  
  1598. ARGUMENT_TAG REF_AslBeginMethod[] =   {
  1599.                                        'TAGL', sizeof(void *),
  1600.                                                sizeof(struct TagItem),
  1601.                                        TAG_END
  1602.                                     };
  1603. void AslBeginMethod(METHOD_ARGS, struct TagItem *tags)
  1604. {
  1605.    struct AslRequest *ar = FindAttribute(object, ATTR_ASLREQUEST);
  1606.    struct TagItem *t;
  1607.  
  1608.  
  1609.    if (ar->ar_OpenFlag & (ASL_FLAG_BEGUN | ASL_FLAG_REMOVE))
  1610.       return;
  1611.  
  1612.    ar->ar_OpenFlag |= ASL_FLAG_BEGUN;
  1613.  
  1614.    if (t = FindTagItem(ASL_Window, tags))
  1615.    {
  1616.       struct Window *win;
  1617.  
  1618.       win = (struct Window *)t->ti_Data;
  1619.       DropObject(SetObject(&ar->ar_LocalWindow,
  1620.                            UseObject((OBJECT)win->UserData)));
  1621.       DropObject(SetObject(&ar->ar_ParentWindow, NULL));
  1622.    }
  1623.  
  1624.    if ((ar->ar_gadType == ASL_FontRequest) &&
  1625.        (t = FindTagItem(ASL_FontName, tags)))
  1626.       t->ti_Data = (ULONG)(ar->ar_FontName = UseString((char *)t->ti_Data));
  1627.  
  1628.    if (ar->ar_gadType == ASL_FileRequest)
  1629.    {
  1630.       if (t = FindTagItem(ASL_File, tags))
  1631.          t->ti_Data = (ULONG)(ar->ar_File = UseString((char *)t->ti_Data));
  1632.       if (t = FindTagItem(ASL_Dir, tags))
  1633.          t->ti_Data = (ULONG)(ar->ar_Dir = UseString((char *)t->ti_Data));
  1634.    }
  1635.  
  1636.    if (t = FindTagItem(ASL_OKText, tags))
  1637.       t->ti_Data = (ULONG)(ar->ar_OKText = UseString((char *)t->ti_Data));
  1638.  
  1639.    if (t = FindTagItem(ASL_CancelText, tags))
  1640.       t->ti_Data = (ULONG)(ar->ar_CancelText = UseString((char *)t->ti_Data));
  1641.  
  1642.    DoShadow(object, NULL, METH_ASL_LAUNCH, tags, METHOD_END);
  1643. }
  1644.  
  1645. void AslLaunchMethod(METHOD_ARGS, struct TagItem *tags)
  1646. {
  1647.    struct AslRequest *ar = FindAttribute(object, ATTR_ASLREQUEST);
  1648.  
  1649.    DoShadow(object,
  1650.                 NULL,
  1651.                 METH_ASL_DONE,
  1652.                 (void *)AslRequest(ar->ar_FileRequester, tags),
  1653.                 METHOD_END);
  1654. }
  1655.  
  1656. ARGUMENT_TAG REF_AslDoneMethod[] =  {
  1657.                                     'long', 4, 0,
  1658.                                     TAG_END
  1659.                                  };
  1660.  
  1661. void AslDoneMethod(METHOD_ARGS, long succeed)
  1662. {
  1663.    OBJECT output;
  1664.    struct AslRequest *ar;
  1665.    struct OutputStruct *io;
  1666.  
  1667.    ar = FindAttribute(object, ATTR_ASLREQUEST);
  1668.  
  1669.    DropString(ar->ar_FontName);
  1670.    DropString(ar->ar_File);
  1671.    DropString(ar->ar_Dir);
  1672.    DropString(ar->ar_OKText);
  1673.    DropString(ar->ar_CancelText);
  1674.    DropObject(SetObject(&ar->ar_LocalWindow, NULL));
  1675.  
  1676.    ar->ar_FontName = NULL;
  1677.    ar->ar_File = NULL;
  1678.    ar->ar_Dir = NULL;
  1679.    ar->ar_OKText = NULL;
  1680.    ar->ar_CancelText = NULL;
  1681.  
  1682.    ar->ar_OpenFlag &= ~ASL_FLAG_BEGUN;
  1683.  
  1684.    io = FindAttribute(object, ATTR_GUIOUTPUT);
  1685.    output = GetObject(&io->out_object);
  1686.  
  1687.    DoShadow(output, NULL, io->out_method, object, succeed, METHOD_END);
  1688.    DropObject(output);
  1689.  
  1690.    if (ar->ar_OpenFlag & ASL_FLAG_REMOVE)
  1691.    {
  1692.       DropObject(SetObject(&ar->ar_ParentWindow, NULL));
  1693.    }
  1694. }
  1695.  
  1696. void AslRemoveMethod(METHOD_ARGS)
  1697. {
  1698.    struct AslRequest *ar;
  1699.  
  1700.    ar = FindAttribute(object, ATTR_ASLREQUEST);
  1701.  
  1702.    ar->ar_OpenFlag |= ASL_FLAG_REMOVE;
  1703.    if (!(ar->ar_OpenFlag & ASL_FLAG_BEGUN))
  1704.    {
  1705.       DropObject(SetObject(&ar->ar_LocalWindow, NULL));
  1706.       DropObject(SetObject(&ar->ar_ParentWindow, NULL));
  1707.    }
  1708.    CallSuper();
  1709. }
  1710.  
  1711. void AslDestroyMethod(METHOD_ARGS)
  1712. {
  1713.    struct AslRequest *ar;
  1714.  
  1715.    ar = FindAttribute(object, ATTR_ASLREQUEST);
  1716.  
  1717.    FreeAslRequest(ar->ar_Requester);
  1718.    ar->ar_Requester = NULL;
  1719.    CallSuper();
  1720. }
  1721.  
  1722. /*
  1723.  ==============================================================================
  1724.  =                                                                            =
  1725.  =                            SUPPLEMENTARY                                   =
  1726.  =                                                                            =
  1727.  ==============================================================================
  1728.  */
  1729. void HandleIntuiMessage(struct IntuiMessage *intui)
  1730. {
  1731.    OBJECT winObject, gadObject;
  1732.    int class;
  1733.  
  1734.    if (!intui)
  1735.       return;
  1736.  
  1737.    winObject = UseObject((OBJECT)intui->IDCMPWindow->UserData);
  1738.  
  1739.    switch(class = intui->Class) {
  1740.  
  1741.       case NEWSIZE:
  1742.          DoShadow(winObject,
  1743.                       NULL,
  1744.                       METH_GUI_RESIZE,
  1745.                       (void *)intui->IDCMPWindow->LeftEdge,
  1746.                       (long)intui->IDCMPWindow->TopEdge,
  1747.                       (long)intui->IDCMPWindow->Width,
  1748.                       (long)intui->IDCMPWindow->Height,
  1749.                       METHOD_END);
  1750.          break;
  1751.  
  1752.       case CLOSEWINDOW:
  1753.       {
  1754.          struct IntuiMessage intui2 = *intui;
  1755.  
  1756.          GT_ReplyIMsg(intui);
  1757.          DoShadow(winObject,
  1758.                       NULL,
  1759.                       METH_WINDOW_CLOSE,
  1760.                       &intui2.Class,
  1761.                       winObject,
  1762.                       METHOD_END);
  1763.          break;
  1764.       }
  1765.  
  1766.       case NEWPREFS:
  1767.       case DISKINSERTED:
  1768.       case DISKREMOVED:
  1769.       case ACTIVEWINDOW:
  1770.       case INACTIVEWINDOW:
  1771.       case CHANGEWINDOW:
  1772.          DoShadow(winObject,
  1773.                       NULL,
  1774.                       METH_GUI_STATE,
  1775.                       &intui->Class,
  1776.                       winObject,
  1777.                       METHOD_END);
  1778.          break;
  1779.  
  1780.       case MOUSEBUTTONS:
  1781.       case MOUSEMOVE:
  1782.       case RAWKEY:
  1783.       case DELTAMOVE:
  1784.       case VANILLAKEY:
  1785.       case INTUITICKS:
  1786.          gadObject = GetObject(&__GlobalFocus);
  1787.          DoShadow((gadObject)?gadObject:winObject,
  1788.                       NULL,
  1789.                       METH_GUI_STATE,
  1790.                       &intui->Class,
  1791.                       winObject,
  1792.                       METHOD_END);
  1793.          DropObject(gadObject);
  1794.          break;
  1795.  
  1796.       case REFRESHWINDOW:
  1797.          GT_BeginRefresh(intui->IDCMPWindow);
  1798.          DoShadow(winObject,
  1799.               NULL,
  1800.               METH_WINDOW_REFRESH,
  1801.               &intui->Class,
  1802.               winObject,
  1803.               METHOD_END);
  1804.          GT_EndRefresh(intui->IDCMPWindow, TRUE);
  1805.          break;
  1806.  
  1807.       case GADGETDOWN:
  1808.       case GADGETUP:
  1809.          gadObject = GetObject((OBJECT *)&
  1810.                                 ((struct Gadget *)intui->IAddress)->UserData);
  1811.          DoShadow(gadObject, NULL, METH_GUI_STATE,
  1812.                                        &intui->Class,
  1813.                                        winObject,
  1814.                                        METHOD_END);
  1815.          DropObject(gadObject);
  1816.          break;
  1817.  
  1818.       default:
  1819.          break;
  1820.    }
  1821.  
  1822.    if (class != CLOSEWINDOW)
  1823.       GT_ReplyIMsg(intui);
  1824.  
  1825.    DropObject(winObject);
  1826. }
  1827.  
  1828. void RemoveWinSafely(struct Window *win)
  1829. {
  1830.    void *object;
  1831.  
  1832.    object = win->UserData;
  1833.    if (win->UserPort)
  1834.    {
  1835.       Forbid();
  1836.       StripIntuiMessages(win->UserPort, win);
  1837.       win->UserPort = NULL;
  1838.       ModifyIDCMP(win, NULL);
  1839.       win->UserData = NULL;
  1840.       Permit();
  1841.  
  1842.       /*
  1843.        * stop using this object in window structure.
  1844.        */
  1845.       DropObject(object);
  1846.    }
  1847. }
  1848.  
  1849. void StripIntuiMessages(struct MsgPort *port, struct Window *win)
  1850. {
  1851.    struct IntuiMessage *msg;
  1852.    struct Node *succ;
  1853.  
  1854.    msg = (struct IntuiMessage *)port->mp_MsgList.lh_Head;
  1855.  
  1856.    while(succ = msg->ExecMessage.mn_Node.ln_Succ)
  1857.    {
  1858.       if (msg->IDCMPWindow == win)
  1859.       {
  1860.          Remove(msg);
  1861.          ReplyMsg(msg);
  1862.       }
  1863.       msg = (struct IntuiMessage *)succ;
  1864.    }
  1865. }
  1866.